local function IsEmpty(vector)
	local point = util.PointContents(vector)
	local a = point ~= CONTENTS_SOLID 
	and point ~= CONTENTS_MOVEABLE 
	and point ~= CONTENTS_LADDER 
	and point ~= CONTENTS_PLAYERCLIP 
	and point ~= CONTENTS_MONSTERCLIP
	local b = true
	
	for k,v in pairs(ents.FindInSphere(vector, 35)) do
		if v:IsNPC() or v:IsPlayer() or v:GetClass() == "prop_physics" then
			b = false
		end
	end
	return a and b
end

local CivModels = {
	"models/player/group01/male_01.mdl",
	"models/player/Group01/Male_02.mdl",
	"models/player/Group01/male_03.mdl",
	"models/player/Group01/Male_04.mdl",
	"models/player/Group01/Male_05.mdl",
	"models/player/Group01/Male_06.mdl",
	"models/player/Group01/Male_07.mdl",
	"models/player/Group01/Male_08.mdl",
	"models/player/Group01/Male_09.mdl"
}

//End of needed things for work

function GM:PlayerDeath(ply, weapon, killer)
	if GetGlobalInt("deathblack") == 1 then
		local RP = RecipientFilter()
		RP:RemoveAllPlayers()
		RP:AddPlayer(ply)
		umsg.Start("DarkRPEffects", RP)
			umsg.String("colormod")
			umsg.String("1")
		umsg.End()
		RP:AddAllPlayers()
	end
	UnDrugPlayer(ply)

	if weapon:IsVehicle() and weapon:GetDriver():IsPlayer() then killer = weapon:GetDriver() end
	if GetGlobalInt("deathnotice") == 1 then
		self.BaseClass:PlayerDeath(ply, weapon, killer)
	end

	ply:Extinguish()

	if ply:InVehicle() then ply:ExitVehicle() end

	if RPArrestedPlayers[ply:SteamID()] then
		-- If the player died in jail, make sure they can't respawn until their jail sentance is over
		ply.NextSpawnTime = CurTime() + math.ceil(GetGlobalInt("jailtimer") - (CurTime() - ply.LastJailed)) + 1
		for a, b in pairs(player.GetAll()) do
			b:PrintMessage(HUD_PRINTCENTER, ply:Nick() .. " has died in jail!")
		end
		Notify(ply, 4, 4, "You now are dead until your jail time is up!")
	else
		-- Normal death, respawning.
		ply.NextSpawnTime = CurTime() + CfgVars["respawntime"]
	end
	ply:GetTable().DeathPos = ply:GetPos()

	if CfgVars["dmautokick"] == 1 and killer:IsPlayer() and killer ~= ply then
		if not killer.kills or killer.kills == 0 then
			killer.kills = 1
			timer.Simple(CfgVars["dmgracetime"], killer.ResetDMCounter, killer)
		else
			-- if this player is going over their limit, kick their ass
			if killer.kills + 1 > CfgVars["dmmaxkills"] then
				game.ConsoleCommand("kickid " .. killer:UserID() .. " Auto-kicked. Excessive Deathmatching.\n")
			else
				-- killed another player
				killer.kills = killer.kills + 1
			end
		end
	end

	if ply ~= killer or ply:GetTable().Slayed then
		ply:SetNetworkedBool("wanted", false)
		RPArrestedPlayers[ply:SteamID()] = false
		ply:GetTable().DeathPos = nil
		ply:GetTable().Slayed = false
	end
	ply:GetTable().ConfisquatedWeapons = nil
	if DB.RetrieveMoney(ply) > 0 then
		DropMoney(ply, DB.RetrieveMoney(ply))
	end
end

function GM:PlayerSpawn(ply)
	self.BaseClass:PlayerSpawn(ply)
	if !ply.WasSleeping then
		if (ply:Team() == TEAM_CHIEF) then
			ply:ChangeTeam(TEAM_POLICE)
		end
		if (ply:Team() == TEAM_MOB) then
			ply:ChangeTeam(TEAM_GANG)
		end
		if (ply:Team() != TEAM_POLICE) and (ply:Team() != TEAM_GANG) and (ply:Team() != TEAM_CITIZEN) and (ply:Team() != TEAM_HOBO) then
			ply:ChangeTeam(TEAM_CITIZEN)
		end
	else
		ply.WasSleeping = false
	end

	ply:CrosshairEnable()

	if CfgVars["crosshair"] == 0 then
		ply:CrosshairDisable()
	end
	ply:GetTable().RPLicenseSpawn = true
	timer.Simple(1, removelicense, ply)
	
	--Kill any colormod anyway
	local RP = RecipientFilter()
	RP:RemoveAllPlayers()
	RP:AddPlayer(ply)
	umsg.Start("DarkRPEffects", RP)
		umsg.String("colormod")
		umsg.String("0")
	umsg.End()
	RP:AddAllPlayers()

	if CfgVars["strictsuicide"] == 1 and ply:GetTable().DeathPos then
		if not (RPArrestedPlayers[ply:SteamID()]) then
			ply:SetPos(ply:GetTable().DeathPos)
		end
	end
	
	-- If the player for some magical reason managed to respawn while jailed then re-jail the bastard.
	if RPArrestedPlayers[ply:SteamID()] and ply:GetTable().DeathPos then
		-- For when CfgVars["teletojail"] == 0
		ply:SetPos(ply:GetTable().DeathPos)
		-- Not getting away that easily, Sonny Jim.
		if DB.RetrieveJailPos() then
			ply:Arrest()
		else
			Notify(ply, 1, 4, "You're no longer under arrest because no jail positions are set!")
		end
	end
	
	if CfgVars["customspawns"] == 1 then
		if not RPArrestedPlayers[ply:SteamID()] then
			local pos = DB.RetrieveTeamSpawnPos(ply)
			if pos then
				ply:SetPos(pos)
			end
		end
	end
	
	local STARTPOS = ply:GetPos()
	if not IsEmpty(STARTPOS) then
		local found = false
		for i = 40, 300, 15 do
			if IsEmpty(STARTPOS + Vector(i, 0, 0)) then
				ply:SetPos(STARTPOS + Vector(i, 0, 0))
				--Yeah I found a nice position to put the player in!
				found = true
				break
			end
		end
		if not found then
			for i = 40, 300, 15 do
				if IsEmpty(STARTPOS + Vector(0, i, 0)) then
					ply:SetPos(STARTPOS + Vector(0, i, 0))
					found = true
					break
				end
			end
		end
		if not found then
			for i = 40, 300, 15 do
				if IsEmpty(STARTPOS + Vector(0, -i, 0)) then
					ply:SetPos(STARTPOS + Vector(0, -i, 0))
					found = true
					break
				end
			end
		end
		if not found then
			for i = 40, 300, 15 do
				if IsEmpty(STARTPOS + Vector(-i, 0, 0)) then
					ply:SetPos(STARTPOS + Vector(-i, 0, 0))
					--Yeah I found a nice position to put the player in!
					found = true
					break
				end
			end
		end
		-- If you STILL can't find it, you'll just put him on top of the other player lol
		if not found then
			ply:SetPos(ply:GetPos() + Vector(0,0,70))
		end
	end

	if CfgVars["babygod"] == 1 and ply:GetNWInt("slp") ~= 1 then
		ply:SetNWBool("Babygod", true)
		ply:GodEnable()
		local r,g,b,a = ply:GetColor()
		ply:SetColor(r, g, b, 100)
		ply:SetCollisionGroup(  COLLISION_GROUP_WORLD )
		timer.Simple(CfgVars["babygodtime"] or 5, function()
			if not ValidEntity(ply) then return end
			ply:SetNWBool("Babygod", false)
			ply:SetColor(r, g, b, a)
			ply:GodDisable()
			ply:SetCollisionGroup( COLLISION_GROUP_PLAYER )
		end)
	end
	ply:SetNWInt("slp", 0)
	if CfgVars["enforceplayermodel"] == 1 then
		if ply:Team() == TEAM_CITIZEN then
			local validmodel = false

			for k, v in pairs(CivModels) do
				if ply:GetTable().PlayerModel == v then
					validmodel = true
					break
				end
			end

			if not validmodel then
				ply:GetTable().PlayerModel = nil
			end

			local model = ply:GetModel()

			if model ~= ply:GetTable().PlayerModel then
				for k, v in pairs(CivModels) do
					if v == model then
						ply:GetTable().PlayerModel = model
						validmodel = true
						break
					end
				end

				if not validmodel and not ply:GetTable().PlayerModel then
					ply:GetTable().PlayerModel = CivModels[math.random(1, #CivModels)]
				end

				ply:SetModel(ply:GetTable().PlayerModel)
			end
		elseif ply:Team() == TEAM_POLICE then
			ply:SetModel("models/player/police.mdl")
		elseif ply:Team() == TEAM_MAYOR then
			ply:SetModel("models/player/breen.mdl")
		elseif ply:Team() == TEAM_GANG then
			ply:SetModel("models/player/group03/male_01.mdl")
		elseif ply:Team() == TEAM_MOB  then
			ply:SetModel("models/player/gman_high.mdl")
		elseif ply:Team() == TEAM_GUN then
			ply:SetModel("models/player/monk.mdl")
		elseif ply:Team() == TEAM_MEDIC then
			ply:SetModel("models/player/kleiner.mdl")
		elseif ply:Team() == TEAM_COOK then
			ply:SetModel("models/player/mossman.mdl")
		elseif ply:Team() == TEAM_CHIEF then
			ply:SetModel("models/player/combine_soldier_prisonguard.mdl")
		end
		
		for k,v in pairs(RPExtraTeams) do
			if ply:Team() == (9+k) then
				ply:SetModel(v.model)
			end
		end
	end
	
	GAMEMODE:SetPlayerSpeed(ply, CfgVars["wspd"], CfgVars["rspd"] )
	if ply:Team() == TEAM_CHIEF or ply:Team() == TEAM_POLICE then
		GAMEMODE:SetPlayerSpeed(ply, CfgVars["wspd"], CfgVars["rspd"] + 10 )
	end

	ply:Extinguish()
	if ply:GetActiveWeapon() and ValidEntity(ply:GetActiveWeapon()) then
		ply:GetActiveWeapon():Extinguish()
	end

	if ply.demotedWhileDead then
		ply.demotedWhileDead = nil
		ply:ChangeTeam(TEAM_CITIZEN)
	end
	
	ply:GetTable().StartHealth = ply:Health()
end

function GM:EntityTakeDamage( ent, inflictor, attacker, amount ) 
	local owner = FindPlayer(attacker:GetNWString("Owner"))
	if owner == nil then
		owner = ent
	end
	if !ent:IsPlayer() then
		return
	end
	if ent:IsNPC() then
		return
	end
	if (inflictor:GetClass() == "prop_physics") then
		return true
	end
end

function GM:PlayerLoadout(ply)
	if RPArrestedPlayers[ply:SteamID()] then return end
	
	ply:GetTable().RPLicenseSpawn = true
	timer.Simple(1, removelicense, ply)
	
	local Team = ply:Team()
	
	ply:Give("keys")
	ply:Give("weapon_physcannon")
	ply:Give("gmod_camera")
	
	if CfgVars["toolgun"] == 1 or ply:HasPriv(ADMIN) or ply:HasPriv(PTOOL) then
		ply:Give("gmod_tool")
	end
	
	if CfgVars["pocket"] == 1 then
		ply:Give("pocket")
	end
	
	if CfgVars["physgun"] == 1 or ply:HasPriv(ADMIN) or ply:HasPriv(PHYS) then
		ply:Give("weapon_physgun")
	end
	
	if ply:HasPriv(ADMIN) and CfgVars["AdminsSpawnWithCopWeapons"] == 1 then
		ply:Give("door_ram")
		ply:Give("arrest_stick")
		ply:Give("unarrest_stick")
		ply:Give("stunstick")
		ply:Give("weaponchecker") 
	end

	for k,v in pairs(RPExtraTeams[Team].Weapons) do
		ply:Give(v)
	end
	
	-- Switch to prefered weapon if they have it
	local cl_defaultweapon = ply:GetInfo( "cl_defaultweapon" )
	
	if ply:HasWeapon( cl_defaultweapon ) then
		ply:SelectWeapon( cl_defaultweapon )
	end
end